﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Flurl.Http;
using Newtonsoft.Json.Linq;
using Pay.Core;
using Pay.DTO;

namespace Pay.Service {
	public class LtdPaySign {
		public LtdPaySign() {
		}
#if DEBUG
		private string key="123456";
		private string partner = "4323423423";
		private string api_url = "http://api.sfb.ltd/open";
#else
        private string key="5c6e25caf69b8206cf62c9917b1d3c4b";
		private string partner = "2423467563423";
		private string api_url = "http://api.sfb.ltd/open";
#endif

        public async Task<T> PayGateway<T>(ltd_req model, string url = "") where T : ltd_res, new() {
            var log = IocHelper.Get<ILogHelper>("info");
            model.merchant_no = partner;
            string text = string.Format("{0}&key={1}", sign(JObject.Parse(model.ToJson())), key);
            model.sign = SecureHelper.MD5(text);
            var json = model.ToJson();
            log.Info(json);
            try {
                var resp1 = await (api_url + url).PostJsonAsync(model).ReceiveString();
                log.Info(resp1);
                return resp1.ToObject<T>();
            } catch (FlurlHttpException ex) {
                log.Error(ex.Message);
                return null;
            }
        }
        /// <summary>
        /// 签名
        /// </summary>
        /// <returns>The sign.</returns>
        /// <param name="model">Model.</param>
        private string sign(JObject model) {
            var collection = model.ToObject<SortedDictionary<string, object>>();
            string result = string.Empty;
            foreach (var kv in collection) {
                if (kv.Key == "sign") continue;
                if (kv.Value is JArray) {
                    string str = "";
                    var arrs = kv.Value as JArray;
                    foreach (var obj in arrs) {
                        if (obj.Type.ToString().Equals("String")) continue;
                        str += FillStringBuilder(obj.ToObject<SortedDictionary<string, object>>());
                    }
                    result += str;
                } else if (kv.Value is JObject) {
                    result += FillStringBuilder((kv.Value as JObject).ToObject<SortedDictionary<string, object>>());
                } else {
                    if (kv.Value != null && !string.IsNullOrEmpty(kv.Value.ToString())) {
                        if (kv.Value is DateTime) {
                            result += "&" + kv.Key + "=" + ((DateTime)kv.Value).ToString("yyyy-MM-dd HH:mm:ss");
                        } else
                            result += "&" + kv.Key + "=" + kv.Value;
                    }
                }
            }
            result = result.Trim('&');
            return result;
        }
        private string FillStringBuilder(SortedDictionary<string, object> dic) {
            string result = string.Empty;
            foreach (var kv in dic) {
                if (kv.Value is JObject)
                    result += FillStringBuilder((kv.Value as JObject).ToObject<SortedDictionary<string, object>>());
                else if (kv.Value is JArray) {
                    string str = "";
                    var arrs = kv.Value as JArray;
                    foreach (var obj in arrs) {
                        if (obj.Type.ToString().Equals("String")) continue;
                        str += FillStringBuilder(obj.ToObject<SortedDictionary<string, object>>());
                    }
                    result += str;
                } else {
                    if (kv.Value != null && !string.IsNullOrEmpty(kv.Value.ToString())) {
                        if (kv.Value is DateTime) {
                            result += "&" + kv.Key + "=" + ((DateTime)kv.Value).ToString("yyyy-MM-dd HH:mm:ss");
                        } else
                            result += "&" + kv.Key + "=" + kv.Value;
                    }
                }
            }
            return result;
        }

        public bool VerifySign(ltd_notify model) {
            var log = IocHelper.Get<ILogHelper>("info");
            string text = string.Format("{0}&key={1}", sign(JObject.Parse(model.ToJson())), key);
            log.Info("明文字符串："+text);
            log.Info("明文加密MD5:" + SecureHelper.MD5(text));
            log.Info("初始MD5:" + model.sign);
            return model.sign == SecureHelper.MD5(text);
        }
    }
}
